import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;
import '../models/mcp_tool.dart';

/// MCP 服务类,负责与 MCP 服务器通信
class McpService {
  McpConfig? _config;
  Process? _process;
  StreamSubscription? _stdoutSubscription;
  StreamSubscription? _stderrSubscription;
  StreamSubscription? _sseSubscription;
  final _responseController =
      StreamController<Map<String, dynamic>>.broadcast();
  int _messageId = 0;
  String? _sessionId;
  String? _messageEndpoint;
  String _protocolVersion = '2025-06-18';
  bool _isLegacyMode = false;

  final Map<int, Completer<Map<String, dynamic>>> _pendingRequests = {};

  McpConfig? get config => _config;
  bool get isConnected => _config != null;

  /// 配置 MCP 连接
  Future<void> configure(McpConfig config) async {
    await disconnect();
    _config = config;

    if (config.type == McpConnectionType.cmd) {
      await _connectCmd();
    } else if (config.type == McpConnectionType.sse) {
      await _connectSse();
    }
  }

  /// 通过 SSE/HTTP 连接 MCP 服务器
  Future<void> _connectSse() async {
    if (_config == null || _config!.sseUrl == null) {
      throw Exception('SSE URL not configured');
    }

    try {
      // 尝试使用新协议 (Streamable HTTP)
      await _tryStreamableHttp();
    } catch (e) {
      // 如果失败,尝试旧协议 (HTTP+SSE)
      try {
        await _tryLegacySse();
      } catch (legacyError) {
        throw Exception(
          'Failed to connect via SSE: $e, Legacy attempt: $legacyError',
        );
      }
    }
  }

  /// 尝试使用新版 Streamable HTTP 协议
  Future<void> _tryStreamableHttp() async {
    print('Attempting Streamable HTTP transport...');
    _protocolVersion = '2025-06-18';
    await _initialize();
    print('Successfully connected using Streamable HTTP');
  }

  /// 尝试使用旧版 HTTP+SSE 协议
  Future<void> _tryLegacySse() async {
    print('🔄 Attempting legacy HTTP+SSE transport...');
    _protocolVersion = '2024-11-05';
    _isLegacyMode = true;

    print('📡 Connecting to SSE endpoint: ${_config!.sseUrl}');

    // 旧协议需要先 GET SSE 端点获取消息端点
    final sseClient = http.Client();
    final request = http.Request('GET', Uri.parse(_config!.sseUrl!));
    request.headers['Accept'] = 'text/event-stream';
    request.headers.addAll(_config!.headers ?? {});

    print('📤 Sending GET request with headers: ${request.headers}');

    final response = await sseClient.send(request);

    print('📥 Received response: ${response.statusCode}');

    if (response.statusCode != 200) {
      throw Exception(
        'Failed to connect to SSE endpoint: ${response.statusCode}',
      );
    }

    // 监听 SSE 流,查找 endpoint 事件并保持连接
    final completer = Completer<void>();
    String? currentEvent;

    _sseSubscription = response.stream
        .transform(utf8.decoder)
        .transform(const LineSplitter())
        .listen(
          (line) {
            print('📨 SSE line: $line');

            if (line.isEmpty) {
              // 空行表示事件结束
              currentEvent = null;
              return;
            }

            if (line.startsWith('event:')) {
              currentEvent = line.substring(6).trim();
              print('🎯 Event type: $currentEvent');
            } else if (line.startsWith('data:')) {
              final data = line.substring(5).trim();
              print('📦 Data: $data');

              try {
                if (currentEvent == 'endpoint' && _messageEndpoint == null) {
                  // 解析 endpoint 事件
                  // 支持两种格式：
                  // 1. 标准格式：{"endpoint":"/messages"}
                  // 2. 非标准格式：直接是路径字符串，如 "/message?sessionId=xxx"

                  if (data.startsWith('{')) {
                    // 标准 JSON 格式
                    final json = jsonDecode(data);
                    if (json is Map && json.containsKey('endpoint')) {
                      _messageEndpoint = json['endpoint'];
                      print(
                        '✅ Found message endpoint (JSON): $_messageEndpoint',
                      );
                      if (!completer.isCompleted) {
                        completer.complete();
                      }
                    }
                  } else if (data.startsWith('/')) {
                    // 非标准格式，直接是路径
                    _messageEndpoint = data;
                    print(
                      '✅ Found message endpoint (plain): $_messageEndpoint',
                    );
                    if (!completer.isCompleted) {
                      completer.complete();
                    }
                  } else {
                    print('⚠️ Unknown endpoint format: $data');
                  }
                } else if (currentEvent == 'message' ||
                    (currentEvent == null && data.startsWith('{'))) {
                  // 解析 JSON-RPC 消息（响应通过 SSE 返回）
                  try {
                    final json = jsonDecode(data);
                    if (json is Map<String, dynamic>) {
                      final methodOrId = json['method'] ?? 'id:${json['id']}';
                      print('💬 Handling SSE message: $methodOrId');
                      print('   Message keys: ${json.keys.toList()}');
                      if (json.containsKey('result')) {
                        print('   Has result: ${json['result'].runtimeType}');
                      }
                      _handleMessage(json);
                    }
                  } catch (e) {
                    print('❌ Failed to parse JSON-RPC message: $e');
                    print('   Raw data: $data');
                  }
                }
              } catch (e) {
                print('❌ Failed to parse data: $e');
              }
            }
          },
          onError: (error) {
            print('❌ SSE stream error: $error');
            if (!completer.isCompleted) {
              completer.completeError(error);
            }
          },
          onDone: () {
            print('⚠️ SSE stream closed');
          },
        );

    // 等待获取消息端点或超时
    print('⏳ Waiting for message endpoint...');
    await completer.future.timeout(
      const Duration(seconds: 10),
      onTimeout: () {
        throw Exception('Timeout waiting for message endpoint');
      },
    );

    print('🚀 Message endpoint ready, initializing...');

    // 初始化连接
    await _initialize();
    print('✅ Successfully connected using legacy HTTP+SSE');
  }

  /// 查找命令的完整路径
  Future<String?> _findCommandPath(String command) async {
    // 如果已经是绝对路径，直接返回
    if (command.startsWith('/')) {
      return command;
    }

    // 常见的命令路径（优先级从高到低）
    final searchPaths = [
      '/usr/local/bin',
      '/opt/homebrew/bin',  // Apple Silicon Mac
      '/usr/bin',
      '/bin',
      Platform.environment['HOME'] != null 
          ? '${Platform.environment['HOME']}/.nvm/versions/node/*/bin' 
          : null,
    ].whereType<String>();

    // 尝试在每个路径中查找命令
    for (final path in searchPaths) {
      final fullPath = '$path/$command';
      final file = File(fullPath);
      
      // 处理 NVM 路径（包含通配符）
      if (path.contains('*')) {
        try {
          final parentDir = Directory(path.replaceAll('/*/bin', ''));
          if (await parentDir.exists()) {
            await for (final entity in parentDir.list()) {
              if (entity is Directory) {
                final nvmCommandPath = '${entity.path}/bin/$command';
                if (await File(nvmCommandPath).exists()) {
                  print('   ✓ Found command at: $nvmCommandPath');
                  return nvmCommandPath;
                }
              }
            }
          }
        } catch (e) {
          // 忽略 NVM 路径查找错误
        }
      } else if (await file.exists()) {
        print('   ✓ Found command at: $fullPath');
        return fullPath;
      }
    }

    // 使用 which 命令查找（最后的手段）
    try {
      final result = await Process.run('which', [command]);
      if (result.exitCode == 0) {
        final path = (result.stdout as String).trim();
        if (path.isNotEmpty) {
          print('   ✓ Found command via which: $path');
          return path;
        }
      }
    } catch (e) {
      print('   ✗ which command failed: $e');
    }

    print('   ✗ Command not found: $command');
    return null;
  }

  /// 通过命令行连接 MCP 服务器
  Future<void> _connectCmd() async {
    if (_config == null || _config!.command == null) {
      throw Exception('Command not configured');
    }

    try {
      print('🚀 Starting MCP process...');
      print('   Command: ${_config!.command}');
      print('   Args: ${_config!.args}');
      print('   Env: ${_config!.env}');

      String command = _config!.command!;
      List<String> args = _config!.args ?? [];
      Map<String, String> environment = {
        ...Platform.environment,
        ...?_config!.env,
      };

      // 增强 PATH 环境变量（包含常见路径）
      final pathParts = [
        '/usr/local/bin',
        '/opt/homebrew/bin',
        '/usr/bin',
        '/bin',
        '/usr/sbin',
        '/sbin',
      ];
      
      // 添加用户目录下的常见路径
      if (Platform.environment['HOME'] != null) {
        final home = Platform.environment['HOME']!;
        pathParts.addAll([
          '$home/.nvm/versions/node/*/bin',
          '$home/.local/bin',
          '$home/bin',
        ]);
      }
      
      // 保留原有的 PATH，并添加新路径
      final existingPath = environment['PATH'] ?? '';
      final newPaths = pathParts.where((p) => !existingPath.contains(p));
      environment['PATH'] = [existingPath, ...newPaths].join(':');
      
      print('   Enhanced PATH: ${environment['PATH']?.substring(0, 150)}...');

      // 统一使用 shell 执行策略（Release 模式下更可靠）
      print('   Using shell execution strategy for reliability');
      
      // 尝试查找命令的完整路径
      String? fullCommandPath;
      if (!command.startsWith('/')) {
        print('   Searching for command: $command');
        fullCommandPath = await _findCommandPath(command);
        
        if (fullCommandPath != null) {
          command = fullCommandPath;
          print('   Using resolved path: $command');
        } else {
          print('   ⚠️ Command not found in standard paths, using shell lookup');
        }
      }

      // 构建完整的命令行
      final allArgs = [command, ...args].join(' ');
      print('   Full command: $allArgs');
      
      // 使用 /bin/sh 执行（最兼容的方式）
      _process = await Process.start(
        '/bin/sh',
        ['-l', '-c', allArgs],  // -l 表示 login shell，会加载用户的环境配置
        environment: environment,
        workingDirectory: Platform.environment['HOME'],
      );

      print('✅ Process started (PID: ${_process!.pid})');

      // 监听标准输出
      _stdoutSubscription = _process!.stdout
          .transform(utf8.decoder)
          .transform(const LineSplitter())
          .listen(_handleStdout);

      // 监听标准错误
      _stderrSubscription = _process!.stderr
          .transform(utf8.decoder)
          .transform(const LineSplitter())
          .listen((line) {
            print('MCP stderr: $line');
          });

      // 等待进程初始化（给进程一点时间启动）
      await Future.delayed(const Duration(milliseconds: 500));

      // 检查进程是否仍在运行
      try {
        final exitCode = await _process!.exitCode.timeout(
          const Duration(milliseconds: 100),
        );
        throw Exception('Process exited with code $exitCode immediately after start');
      } on TimeoutException {
        // 进程仍在运行，这是正常的
        print('✅ Process is running');
      }

      // 初始化连接
      await _initialize();
    } catch (e, stackTrace) {
      print('❌ Failed to start MCP process: $e');
      print('Stack trace: $stackTrace');
      throw Exception('Failed to start MCP process: $e');
    }
  }

  /// 处理标准输出
  void _handleStdout(String line) {
    if (line.trim().isEmpty) return;

    try {
      final json = jsonDecode(line) as Map<String, dynamic>;
      _handleMessage(json);
    } catch (e) {
      print('Failed to parse message: $line, error: $e');
    }
  }

  /// 处理消息
  void _handleMessage(Map<String, dynamic> message) {
    print('🔍 Processing message...');
    print('   ID: ${message['id']}');
    print('   Method: ${message['method']}');
    print('   Has result: ${message.containsKey('result')}');
    print('   Has error: ${message.containsKey('error')}');

    final id = message['id'];

    if (id != null && _pendingRequests.containsKey(id)) {
      print('   ✓ Found pending request for id: $id');
      final completer = _pendingRequests.remove(id);

      if (message.containsKey('error')) {
        print('   ✗ Message contains error: ${message['error']}');
        completer?.completeError(message['error']);
      } else {
        print('   ✓ Completing request with message');
        completer?.complete(message);
      }
    } else {
      // 通知或其他消息
      print(
        '   → Notification or unsolicited message (id: $id, pending: ${_pendingRequests.keys.toList()})',
      );
      _responseController.add(message);
    }
  }

  /// 初始化 MCP 连接
  Future<void> _initialize() async {
    final response = await _sendRequest('initialize', {
      'protocolVersion': '2024-11-05',
      'capabilities': {'tools': {}},
      'clientInfo': {'name': 'mcp-ui', 'version': '1.0.0'},
    });

    print('Initialized: $response');
  }

  /// 发送请求
  Future<Map<String, dynamic>> _sendRequest(
    String method,
    Map<String, dynamic>? params,
  ) async {
    final id = _messageId++;
    final completer = Completer<Map<String, dynamic>>();
    _pendingRequests[id] = completer;

    final message = {
      'jsonrpc': '2.0',
      'id': id,
      'method': method,
      if (params != null) 'params': params,
    };

    if (_config?.type == McpConnectionType.cmd) {
      _process?.stdin.writeln(jsonEncode(message));
    } else if (_config?.type == McpConnectionType.sse) {
      await _sendSseRequest(message);
    }

    // 对于旧版 SSE 协议，响应会通过 SSE 流返回，等待时间可能更长
    final timeout = _isLegacyMode ? 60 : 30;

    return completer.future.timeout(
      Duration(seconds: timeout),
      onTimeout: () {
        _pendingRequests.remove(id);
        print('⏱️ Request timeout after $timeout seconds: $method (id: $id)');
        throw TimeoutException('Request timeout: $method');
      },
    );
  }

  /// 发送 SSE/HTTP 请求
  Future<void> _sendSseRequest(Map<String, dynamic> message) async {
    if (_config?.sseUrl == null) {
      throw Exception('SSE URL not configured');
    }

    try {
      // 确定目标 URL
      String targetUrl = _config!.sseUrl!;
      if (_messageEndpoint != null) {
        // 使用旧协议的消息端点
        final uri = Uri.parse(_config!.sseUrl!);
        targetUrl = '${uri.scheme}://${uri.host}:${uri.port}$_messageEndpoint';
        print('📤 Using legacy message endpoint: $targetUrl');
      } else {
        print('📤 Using Streamable HTTP endpoint: $targetUrl');
      }

      final headers = {
        'Content-Type': 'application/json',
        'Accept': 'application/json, text/event-stream',
        ..._config!.headers ?? {},
      };

      // 新版协议需要协议版本头
      if (!_isLegacyMode) {
        headers['MCP-Protocol-Version'] = _protocolVersion;
      }

      // 如果有会话 ID,添加到请求头
      if (_sessionId != null) {
        headers['Mcp-Session-Id'] = _sessionId!;
      }

      print('📨 Sending ${message['method']} (id: ${message['id']})');
      print('   Headers: $headers');
      print('   Body: ${jsonEncode(message)}');

      final response = await http
          .post(
            Uri.parse(targetUrl),
            headers: headers,
            body: jsonEncode(message),
          )
          .timeout(const Duration(seconds: 5));

      print('📥 Response: ${response.statusCode}');
      print('   Content-Type: ${response.headers['content-type']}');

      // 检查并保存会话 ID
      if (response.headers.containsKey('mcp-session-id')) {
        _sessionId = response.headers['mcp-session-id'];
        print('🔑 Received session ID: $_sessionId');
      }

      if (response.statusCode == 200) {
        // 检查响应类型
        final contentType = response.headers['content-type'];
        if (contentType?.contains('application/json') == true) {
          // JSON 响应
          print('📦 JSON response: ${response.body}');
          final json = jsonDecode(response.body) as Map<String, dynamic>;
          _handleMessage(json);
        } else if (contentType?.contains('text/event-stream') == true) {
          // SSE 流响应,处理流中的消息
          print('📡 SSE stream response');
          _handleSseStream(response.body);
        } else {
          print('⚠️ Unknown content type: $contentType');
          print('   Body: ${response.body}');
        }
      } else if (response.statusCode == 202) {
        // 202 Accepted - 通知或响应已接受（旧版协议响应通过 SSE 返回）
        print('✅ Request accepted: ${message['method']}');
        print('⏳ Waiting for response from SSE stream...');
        // 旧版协议：POST 请求只是发送消息，实际响应会通过 SSE 流返回
        // _handleMessage 会在 SSE 监听器中被调用
      } else if (response.statusCode == 400) {
        // 400 可能是 sessionId 无效
        print('❌ Bad request (possibly invalid session)');
        print('   Body: ${response.body}');

        // 尝试解析错误
        try {
          final json = jsonDecode(response.body);
          if (json is Map && json.containsKey('error')) {
            final id = message['id'] as int?;
            if (id != null && _pendingRequests.containsKey(id)) {
              final completer = _pendingRequests.remove(id);
              completer?.completeError(
                json['error']['message'] ?? json['error'],
              );
            }
          }
        } catch (_) {}

        throw Exception(
          'HTTP request failed: ${response.statusCode} - ${response.body}',
        );
      } else if (response.statusCode == 404) {
        // 会话已过期,需要重新初始化
        _sessionId = null;
        print('⚠️ Session expired, need to reconnect');
        throw Exception('Session expired, please reconnect');
      } else {
        print('❌ HTTP error: ${response.statusCode}');
        print('   Body: ${response.body}');
        throw Exception(
          'HTTP request failed: ${response.statusCode} - ${response.body}',
        );
      }
    } catch (e) {
      print('❌ Request failed: $e');
      // 将错误传递给等待的请求
      final id = message['id'] as int?;
      if (id != null && _pendingRequests.containsKey(id)) {
        final completer = _pendingRequests.remove(id);
        completer?.completeError(e);
      }
      rethrow;
    }
  }

  /// 处理 SSE 流响应
  void _handleSseStream(String body) {
    final lines = body.split('\n');
    for (var line in lines) {
      if (line.startsWith('data:')) {
        try {
          final json = jsonDecode(line.substring(5).trim());
          if (json is Map<String, dynamic>) {
            _handleMessage(json);
          }
        } catch (e) {
          print('Failed to parse SSE data: $e');
        }
      }
    }
  }

  /// 列出可用的工具
  Future<List<McpTool>> listTools() async {
    try {
      print('🔧 Listing tools...');
      final response = await _sendRequest('tools/list', null);
      print('📋 Tools response received');
      print('   Full response: ${response.toString()}');
      print('   Has result key: ${response.containsKey('result')}');

      if (response.containsKey('error')) {
        print('❌ Server returned error: ${response['error']}');
        return [];
      }

      final result = response['result'];
      print('   Result type: ${result.runtimeType}');
      print('   Result value: $result');

      if (result == null) {
        print('⚠️ Result is null');
        return [];
      }

      final tools = result['tools'] as List<dynamic>?;
      print('   Tools type: ${tools.runtimeType}');
      print('   Tools length: ${tools?.length ?? 0}');

      if (tools == null) {
        print('⚠️ No tools found in result');
        print('   Available keys in result: ${result.keys}');
        return [];
      }

      if (tools.isEmpty) {
        print('⚠️ Tools list is empty');
        return [];
      }

      print('✅ Found ${tools.length} tools, parsing...');
      final toolsList = <McpTool>[];

      for (var i = 0; i < tools.length; i++) {
        try {
          print('   Parsing tool $i: ${tools[i]}');
          final tool = McpTool.fromMcpFormat(tools[i] as Map<String, dynamic>);
          toolsList.add(tool);
          print('   ✓ ${tool.name}: ${tool.description}');
        } catch (e) {
          print('   ✗ Failed to parse tool $i: $e');
        }
      }

      print('🎉 Successfully parsed ${toolsList.length} tools');
      return toolsList;
    } catch (e, stackTrace) {
      print('❌ Failed to list tools: $e');
      print(
        'Stack trace: ${stackTrace.toString().split('\n').take(3).join('\n')}',
      );
      return [];
    }
  }

  /// 调用工具
  Future<McpToolResult> callTool(
    String toolName,
    Map<String, dynamic> arguments,
  ) async {
    try {
      final response = await _sendRequest('tools/call', {
        'name': toolName,
        'arguments': arguments,
      });

      final result = response['result'];

      return McpToolResult(toolName: toolName, success: true, result: result);
    } catch (e) {
      return McpToolResult(
        toolName: toolName,
        success: false,
        error: e.toString(),
      );
    }
  }

  /// 断开连接
  Future<void> disconnect() async {
    print('🔌 Disconnecting...');
    await _stdoutSubscription?.cancel();
    await _stderrSubscription?.cancel();
    await _sseSubscription?.cancel();
    _process?.kill();
    _process = null;
    _config = null;
    _messageEndpoint = null;
    _sessionId = null;
    _isLegacyMode = false;
    _pendingRequests.clear();
    print('✅ Disconnected');
  }

  /// 释放资源
  void dispose() {
    disconnect();
    _responseController.close();
  }
}
